package com.ekuaitu.kuaitustaff.utils.ble;

import com.ekuaitu.kuaitustaff.utils.Logger;

import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/**
 * Created by michaelpi on 2018/4/11.
 */

public class BSJParseUtils {
    private static final BSJParseUtils instance = new BSJParseUtils();
    private byte[] keyBytes = new byte[16];
    private byte[] pswBytes = new byte[6];
    public byte[] token = new byte[4];

    public static BSJParseUtils getInstance() {
        return instance;
    }

    private BSJParseUtils() {
    }

    void parsePswKey(String psw, String key) {
        //解析密钥
        String[] KEY = key.split(",");
        for (int i = 0; i < 16; i++) {
            keyBytes[i] = Byte.parseByte(KEY[i]);
        }
        //解析密码
        byte[] allPsw = psw.getBytes();
        System.arraycopy(allPsw, 0, pswBytes, 0, 6);
    }

    boolean parseToken(byte[] rawData) {
        //四个参数：源数组，源数组要复制的起始位置，目的数组，目的数组放置的起始位置，复制的长度
        System.arraycopy(rawData, 3, token, 0, 4);
        return token != null;
    }


    int[] parseStatus(byte[] data) {
        //取出字节的位，1:开  0:关
        int[] statusArray = new int[16];
        for (int i = 0; i < 8; i++) {
            statusArray[i] = ((data[4] & (1 << i)) != 0 ? 1 : 0);
        }
        for (int i = 8; i < 16; i++) {
            statusArray[i] = ((data[3] & (1 << i - 8)) != 0 ? 1 : 0);
        }

        int[] status = new int[16];
        status[BleConstants.CarStatus.FL_DOOR] = statusArray[14] == 1 ? 0 : 1;
        status[BleConstants.CarStatus.FR_DOOR] = statusArray[8];
        status[BleConstants.CarStatus.RL_DOOR] = statusArray[9];
        status[BleConstants.CarStatus.RR_DOOR] = statusArray[7];

        status[BleConstants.CarStatus.FL_WINDOWS] = statusArray[6];
        status[BleConstants.CarStatus.FR_WINDOWS] = statusArray[4];
        status[BleConstants.CarStatus.RL_WINDOWS] = statusArray[5];
        status[BleConstants.CarStatus.RR_WINDOWS] = statusArray[3];

        status[BleConstants.CarStatus.TRUNK] = statusArray[2];
        status[BleConstants.CarStatus.ENGINE] = statusArray[13];
        status[BleConstants.CarStatus.MILEAGE] = data[8] * 65535 + data[9] * 256 + data[10];
        return status;
    }


    boolean parseDoorStatus(byte[] data) {
        int[] statusArray = new int[16];
        for (int i = 0; i < 8; i++) {
            statusArray[i] = ((data[4] & (1 << i)) != 0 ? 1 : 0);
        }
        for (int i = 8; i < 16; i++) {
            statusArray[i] = ((data[3] & (1 << i - 8)) != 0 ? 1 : 0);
        }
        boolean isClose = true;
        int[] status = new int[5];
        status[0] = statusArray[14];
        status[1] = statusArray[8];
        status[2] = statusArray[9];
        status[3] = statusArray[7];
        status[4] = statusArray[13];
        Logger.i("bleInfo", "B-status" + Arrays.toString(status));
        for (int i = 1; i < 4; i++) {
            if (status[i] == 1) {
                isClose = false;
                break;
            }
        }
        return isClose && status[4] == 0 && status[0] == 1;
    }


    /**
     * 加密
     */
    private byte[] Encrypt(byte[] sSrc) {
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            return cipher.doFinal(sSrc);
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * 解密
     */
    byte[] Decrypt(byte[] sSrc) {
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            return cipher.doFinal(sSrc);
        } catch (Exception ex) {
            return null;
        }
    }


    byte[] createGetTokenCmd() {
        byte[] cmdBytes = {0x06, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C};
        return Encrypt(cmdBytes);
    }

    byte[] createOpenCmd() {
        byte[] cmdBytes = {0x05, 0x01, 0x06, pswBytes[0], pswBytes[1], pswBytes[2], pswBytes[3], pswBytes[4], pswBytes[5], token[0], token[1], token[2], token[3], 0x00, 0x00, 0x00};
        return Encrypt(cmdBytes);
    }

    byte[] createCloseCmd() {
        byte[] cmdBytes = {0x05, 0x07, 0x06, pswBytes[0], pswBytes[1], pswBytes[2], pswBytes[3], pswBytes[4], pswBytes[5], token[0], token[1], token[2], token[3], 0x00, 0x00, 0x00};
        return Encrypt(cmdBytes);
    }

    byte[] createPowerCmd() {
        byte[] cmdBytes = {0x08, 0x12, 0x06, pswBytes[0], pswBytes[1], pswBytes[2], pswBytes[3], pswBytes[4], pswBytes[5], token[0], token[1], token[2], token[3], 0x00, 0x00, 0x00};
        return Encrypt(cmdBytes);
    }

    byte[] createPoweroffCmd() {
        byte[] cmdBytes = {0x08, 0x10, 0x06, pswBytes[0], pswBytes[1], pswBytes[2], pswBytes[3], pswBytes[4], pswBytes[5], token[0], token[1], token[2], token[3], 0x00, 0x00, 0x00};
        return Encrypt(cmdBytes);
    }

    byte[] createResponseCmd(byte[] receivedData) {
        byte[] cmdBytes = {(byte) 0xCB, receivedData[0], receivedData[1], 0x01, 0x00, token[0], token[1], token[2], token[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        return Encrypt(cmdBytes);
    }

    byte[] createStatusCmd() {
        byte[] cmdBytes = {0x02, 0x01, 0x01, 0x01, token[0], token[1], token[2], token[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        return Encrypt(cmdBytes);
    }

    byte[] createFindCmd() {
        byte[] cmdBytes = {0x05, 0x09, 0x06, pswBytes[0], pswBytes[1], pswBytes[2], pswBytes[3], pswBytes[4], pswBytes[5], token[0], token[1], token[2], token[3], 0x00, 0x00, 0x00};
        return Encrypt(cmdBytes);
    }
}
